package com.autoagent.ai_live_master.webSocket.handler;


import com.autoagent.ai_live_master.webSocket.config.SpringEndpointConfigurator;
import com.autoagent.ai_live_master.webSocket.converter.MessageConverter;
import com.autoagent.ai_live_master.webSocket.model.LiveMessage;
import com.autoagent.ai_live_master.webSocket.vo.RealTimeBulletScreenMessage;
import com.autoagent.ai_live_master.webSocket.service.WordCloudService;
import com.autoagent.ai_live_master.webSocket.util.EmojiUtil;
import com.autoagent.ai_live_master.common.event.WebSocketConnectionEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@ServerEndpoint(value= "/ws/live/{roomId}", configurator = SpringEndpointConfigurator.class)
public class LiveWebSocketHandler {

    // 修改这里，嵌套Map结构
    private static final Map<String /* roomId */, Set<Session>> SESSIONS = new ConcurrentHashMap<>();
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    
    // 注入MessageConverter
    private final SocketIOHandler socketIOHandler;
    private final MessageConverter messageConverter;

    private final WordCloudService wordCloudService;
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    // 使用构造器注入，final变量必须在构造器中初始化
    @Autowired
    public LiveWebSocketHandler(SocketIOHandler socketIOHandler, MessageConverter messageConverter,WordCloudService wordCloudService) {
        this.socketIOHandler = socketIOHandler;
        this.messageConverter = messageConverter;
        this.wordCloudService=wordCloudService;
    }
    
    @OnOpen
    public void onOpen(Session session, @PathParam("roomId") String roomId) {
        try {
            session.setMaxTextMessageBufferSize(1024 * 1024);
            session.setMaxBinaryMessageBufferSize(1024 * 1024);

            session.getUserProperties().put("roomId", roomId);


            // 将 session 加入到 roomId 对应的 Set 中
            SESSIONS.computeIfAbsent(roomId, k -> ConcurrentHashMap.newKeySet()).add(session);

            log.info("WebSocket连接已建立，房间ID: {}, 当前连接数: {}, 房间内连接数: {}",
                    roomId, totalSessionCount(), SESSIONS.get(roomId).size());
            
            // 发布WebSocket连接事件，让其他服务处理定式话术发送
            eventPublisher.publishEvent(new WebSocketConnectionEvent(this, roomId, "websocket"));
            log.info("WebSocket连接建立，已发布连接事件，房间ID: {}", roomId);

        } catch (Exception e) {
            log.error("WebSocket连接建立失败，房间ID: {}, 错误: {}", roomId, e.getMessage(), e);
        }
    }

    @OnClose
    public void onClose(Session session) {
        String roomId = (String) session.getUserProperties().get("roomId");
        if (roomId != null) {
            Set<Session> sessions = SESSIONS.get(roomId);
            if (sessions != null) {
                sessions.remove(session);
                if (sessions.isEmpty()) {
                    SESSIONS.remove(roomId); // 可选：房间没人就移除
                }
            }
        }
        log.info("WebSocket连接关闭，房间ID: {}, 当前连接数: {}", roomId, totalSessionCount());
    }


    // 统计所有连接数（方便日志）
    private int totalSessionCount() {
        return SESSIONS.values().stream().mapToInt(Set::size).sum();
    }

    // onMessage 保持现有，广播时需要改成广播给该房间所有source
    @OnMessage
    public void onMessage(String message, @PathParam("roomId") String roomId, Session session) {
        log.info("收到消息，房间ID: {}", roomId);
        try {
            if (message.startsWith("[")) {
                List<LiveMessage> messages = OBJECT_MAPPER.readValue(message,
                        OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, LiveMessage.class));
                for (LiveMessage liveMessage : messages) {
                    processAndBroadcastMessage(roomId, liveMessage);
                }
            } else {
                LiveMessage liveMessage = OBJECT_MAPPER.readValue(message, LiveMessage.class);
                processAndBroadcastMessage(roomId, liveMessage);
            }
        } catch (IOException e) {
            log.error("消息处理失败，错误详情: {}", e.getMessage(), e);
            log.error("原始消息内容: {}", message);
        }
    }



    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket发生错误: {}", error.getMessage(), error);
        onClose(session); // 出错时清理 session
    }

    private void processAndBroadcastMessage(String roomId, LiveMessage liveMessage) {
        try {
            // 确保 roomId 不为空
            if (roomId == null || roomId.trim().isEmpty()) {
                log.error("房间ID为空，无法处理消息");
                return;
            }

            // 确保消息对象不为空
            if (liveMessage == null) {
                log.error("消息对象为空，房间ID: {}", roomId);
                return;
            }

            // 确保消息类型不为空
            if (liveMessage.getMethod() == null || liveMessage.getMethod().trim().isEmpty()) {
                log.error("消息类型为空，房间ID: {}", roomId);
                return;
            }
            
            // 处理消息（例如：emoji转换）
            processMessage(liveMessage);
            
            // 广播WebSocket消息
            broadcastMessage(roomId, liveMessage);
            
        } catch (Exception e) {
            log.error("消息处理和广播失败，房间ID: {}, 错误: {}", roomId, e.getMessage(), e);
        }
    }

    private void processMessage(LiveMessage message) {
        if (message.getContent() != null && EmojiUtil.containsEmoji(message.getContent())) {
            String processedContent = EmojiUtil.convertEmojiToUrl(message.getContent());
            message.setContent(processedContent);
            log.info("消息内容已处理emoji: {}", processedContent);
        }
    }

    /**
     * 广播处理后封装好的 LiveMessage 对象给指定房间所有连接
     * 并根据消息类型转换为不同的消息对象
     */
    private void broadcastMessage(String roomId, LiveMessage message) {
        if (!socketIOHandler.hasConnectedClients(roomId)) {
            log.warn("无法广播消息，当前无活跃连接");
            return;
        }
        try {
            if (messageConverter != null) {
                String originalJson = OBJECT_MAPPER.writeValueAsString(message);

                switch (message.getMethod()) {
                    case "WebcastMemberMessage":
                        RealTimeBulletScreenMessage memberJoinMessage = messageConverter.convertToUnifiedMemberJoinMessage(message);
                        if (memberJoinMessage != null) {
                            String memberJson = OBJECT_MAPPER.writeValueAsString(memberJoinMessage);
                            sendToFrontViaSocketIO(roomId,memberJson, "成员加入");
                        }
                        break;

                    case "WebcastChatMessage":
                        RealTimeBulletScreenMessage chatMessage = messageConverter.convertToUnifiedChatMessage(message);
                        if (chatMessage != null) {
                            String chatJson = OBJECT_MAPPER.writeValueAsString(chatMessage);
                            wordCloudService.addMessage(roomId, message.getContent());
                            sendToFrontViaSocketIO(roomId,chatJson, "聊天");
                        }
                        break;

                    case "WebcastGiftMessage":
                        RealTimeBulletScreenMessage giftMessage = messageConverter.convertToUnifiedGiftMessage(message);
                        if (giftMessage != null) {
                            String giftJson = OBJECT_MAPPER.writeValueAsString(giftMessage);
                            sendToFrontViaSocketIO(roomId,giftJson, "礼物");
                        }
                        break;

                    case "WebcastLikeMessage":
                        RealTimeBulletScreenMessage likeMessage = messageConverter.convertToUnifiedLikeMessage(message);
                        if (likeMessage != null) {
                            String likeJson = OBJECT_MAPPER.writeValueAsString(likeMessage);
                            sendToFrontViaSocketIO(roomId,likeJson, "点赞");
                        }
                        break;

                    case "WebcastSocialMessage":
                        RealTimeBulletScreenMessage socialMessage = messageConverter.convertToUnifiedSocialMessage(message);
                        if (socialMessage != null) {
                            String socialJson = OBJECT_MAPPER.writeValueAsString(socialMessage);
                            sendToFrontViaSocketIO(roomId,socialJson, "社交");
                        }
                        break;

                    case "WebcastRoomUserSeqMessage":
                        RealTimeBulletScreenMessage roomUserSeqMessage = messageConverter.convertToUnifiedRoomUserSeqMessage(message);
                        if (roomUserSeqMessage != null) {
                            String roomUserSeqJson = OBJECT_MAPPER.writeValueAsString(roomUserSeqMessage);
                            sendToFrontViaSocketIO(roomId,roomUserSeqJson, "房间用户信息");
                        }
                        break;

                    case "WebcastConnectMessage":
                        RealTimeBulletScreenMessage connectMessage = messageConverter.convertToUnifiedConnectMessage(message);
                        if (connectMessage != null) {
                            String connectJson = OBJECT_MAPPER.writeValueAsString(connectMessage);
                            sendToFrontViaSocketIO(roomId,connectJson, "连接成功");
                        }
                        break;

                    // 其他不处理的类型略过
                    default:
                        break;
                }
            } else {
                log.warn("MessageConverter未注入，无法转换消息类型");
            }
        } catch (IOException e) {
            log.error("消息广播失败，房间ID: {}, 错误: {}", roomId, e.getMessage(), e);
        }
    }

    private void sendToFrontViaSocketIO(String roomId, String json, String messageType) {
        try {
            socketIOHandler.broadcast(roomId,json);
            log.info("通过Socket.IO发送{}消息成功", messageType);
        } catch (Exception e) {
            log.error("通过Socket.IO发送{}消息失败，错误: {}", messageType, e.getMessage(), e);
        }
    }

}